package com.sina.shop.manage.service.admin;

import com.sina.shop.core.exception.client.DataException;
import com.sina.shop.core.exception.server.CreateException;
import com.sina.shop.core.exception.server.ResourceExistsException;
import com.sina.shop.core.exception.server.UpdateException;
import com.sina.shop.domain.admin.Admin;
import com.sina.shop.domain.admin.Role;
import com.sina.shop.manage.dao.admin.AdminManageDao;
import com.sina.shop.manage.dao.admin.RoleManageDao;
import com.sina.shop.service.ShopDataSourceService;
import com.sina.shop.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

import static com.sina.shop.service.ServiceConstant.SHOP_TX;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * 段浩杰   2017-12-13-18:29
 */
@Service("adminManageService")
public class AdminManageServiceImpl extends ShopDataSourceService implements AdminManageService {

    @Autowired
    @Qualifier("adminManageDao")
    private AdminManageDao adminManageDao;

    @Autowired
    @Qualifier("roleManageDao")
    private RoleManageDao roleManageDao;

    @Override
    @Transactional(readOnly = true, value = SHOP_TX, isolation = Isolation.READ_COMMITTED)
    public Admin getAdmin(String account) {
        return adminManageDao.getAdmin(account);
    }

    @Override
    @Transactional(readOnly = true, value = SHOP_TX, isolation = Isolation.READ_COMMITTED)
    public Admin getAdmin(Long id) {
        return adminManageDao.get(Admin.class, id);
    }

    @Override
    @Transactional(value = SHOP_TX, isolation = Isolation.REPEATABLE_READ)
    public int deleteAdmin(Long id) throws DataException, UpdateException {
        Admin admin = adminManageDao.get(Admin.class, id);
        Assert.assertNotNull(admin, "Admin[id=%s] not exists", admin.getId());

        try {
            return adminManageDao.deleteAdmin(id);
        } catch (DataAccessException e) {
            LOG.error(" {} delete Admin error.", Admin.class, e);
            throw new UpdateException(ResultCode.dataAccessError, e.getMessage(), e);
        }
    }

    @Override
    @Transactional(value = SHOP_TX, isolation = Isolation.REPEATABLE_READ)
    public Admin updateAdmin(Admin admin) throws UpdateException, DataException {
        Admin a = adminManageDao.get(Admin.class, admin.getId());
        Assert.assertNotNull(a, "Admin[id=%s] not exists", admin.getId());

        try {
            a = updateAdminFiled(admin, a);
            adminManageDao.flush();

            return a;
        } catch (DataAccessException e) {
            LOG.error(" {} update Admin error.", Admin.class, e);
            throw new UpdateException(ResultCode.dataAccessError, e.getMessage(), e);
        }
    }

    /**
     * 所需要更新的字段的转换
     *
     * @param oldAdmin 前台传来的admin（瞬时态）
     * @param newAdmin 从数据库中查询的admin（持久态）
     * @return admin   最后要变为的admin（执行完update后变为游离态）
     */
    private Admin updateAdminFiled(Admin oldAdmin, Admin newAdmin) {

        /*根据是否为null来进行添加更新的字段*/
        if (!StringUtils.isEmpty(oldAdmin.getName())) {
            newAdmin.setName(oldAdmin.getName());
        }
        if (!StringUtils.isEmpty(oldAdmin.getPassword())) {
            newAdmin.setPassword(oldAdmin.getPassword());
        }
        if (oldAdmin.getCredit() != null) {
            newAdmin.setCredit(oldAdmin.getCredit());
        }
        if (!StringUtils.isEmpty(oldAdmin.getStatus())) {
            newAdmin.setStatus(oldAdmin.getStatus());
        }
        if (!StringUtils.isEmpty(oldAdmin.getPhoto())) {
            newAdmin.setPhoto(oldAdmin.getPhoto());
        }
        if (!StringUtils.isEmpty(oldAdmin.getSex())) {
            newAdmin.setSex(oldAdmin.getSex());
        }
        if (!StringUtils.isEmpty(oldAdmin.getPhone())) {
            newAdmin.setPhone(oldAdmin.getPhone());
        }
        if (!StringUtils.isEmpty(oldAdmin.getEmail())) {
            newAdmin.setEmail(oldAdmin.getEmail());
        }
        if (oldAdmin.getPreviousLoginTime() != null) {
            newAdmin.setPreviousLoginTime(oldAdmin.getPreviousLoginTime());
        }
        if (!StringUtils.isEmpty(oldAdmin.getIdCard())) {
            newAdmin.setIdCard(oldAdmin.getIdCard());
        }
        if (!StringUtils.isEmpty(oldAdmin.getAddress())) {
            newAdmin.setAddress(oldAdmin.getAddress());
        }
        if (!CollectionUtils.isEmpty(oldAdmin.getRoles())) {
            Set<Role> roles = getUpdateAdminAndRole(oldAdmin.getRoles());
            newAdmin.setRoles(roles);
        }
        return newAdmin;
    }

    /*关联表中所要更新的字段*/
    private Set<Role> getUpdateAdminAndRole(Set<Role> rols) {
        Set<Role> roles = new HashSet<>();
        Iterator<Role> iterator = rols.iterator();
        while (iterator.hasNext()) {
            Role role = iterator.next();
            if (role != null && role.getId() != null) {
                role = roleManageDao.get(Role.class, role.getId());
                roles.add(role);
            }
        }
        return roles;
    }

    @Override
    @Transactional(value = SHOP_TX, isolation = Isolation.REPEATABLE_READ)
    public Admin saveAdmin(Admin admin) throws CreateException, ResourceExistsException, DataException {
        boolean exists;
        exists = adminManageDao.isExistsByUnique(Admin.class, "account", admin.getAccount());
        Assert.assertFalse(exists, ResourceExistsException.class, ResultCode.dataExists
                , "Admin[%s] exists", admin.getAccount());

        //把密码加密进行存储（md5摘要2次，不进行加盐，进行hex存储）
        //String md5Psd = MD5Utils.getEncryptString("MD5", admin.getPassword(), null, 2, true);
        //admin.setPassword(md5Psd);

        try {
            adminManageDao.save(admin);
            adminManageDao.flush();
            return admin;
        } catch (DataAccessException e) {
            LOG.error(" {} save Admin error.", Admin.class, e);
            throw new UpdateException(ResultCode.dataAccessError, e.getMessage(), e);
        }
    }

    @Override
    @Transactional(readOnly = true, value = SHOP_TX, isolation = Isolation.READ_COMMITTED)
    public List<Map<String, Object>> getAdminList(Admin admin, Long[] count) {

        if (count != null && count.length > 0) {
            count[0] = adminManageDao.getAdminCount(admin);
        }

        return adminManageDao.getAdminList(admin);
    }

    @Override
    @Transactional(readOnly = true, value = SHOP_TX, isolation = Isolation.READ_COMMITTED)
    public List<Map<String, Object>> getAdminIdAndNameList() {
        return adminManageDao.getAdminIdAndNameList();
    }
}
